#pragma once

#include <iostream>
#include <cmath>

/// 全局 var，控制变元。
/// 本代码所有函数均为 var 元布尔函数。
const int var = 14;

/*
	头文件中包含函数：

	n 元内积		int cdot(int* x, int* y, int var);
	另一种内积		int inner_dot(int x, int y);
	
	Walsh			int Walsh(const int F[], const int w);
	自相关			int  Autocorrelation(const int F[], const int a);
	Δ_f				int Delat_f(const int* F);
	δ_f				int delat_f(const int* F);
	平衡			bool Balanced(const int F[]);
	最大Walsh绝对值	int Max_Abs_Walsh(const int F[]);
	非线性度		int nonlinear(int* F);
	Bent			bool if_bent(int* f);
	
	汉明距离		int hb(int* bf1, int* bf2);
	真值表等价		bool ifequal(int* bf1, int* bf2);

	打印信息		void print_bf(int* f)

*/


/// n 元布尔向量内积
int cdot(int* x, int* y, int n) {
	int res = 0;
	for (int i = 0; i < n; i++)
	{
		res = res xor (x[i] * y[i]);
	}
	return res;
}

/// Walsh 函数中调用了inner_dot 函数
/// 另一种内积
/// 因为这里使用了十进制数x，y来表示他们的二进制向量
int inner_dot(int x, int y)
{
	int tmp = x & y;//各位做乘法，“&”是按位与运算
	int num = 0;
	while (tmp)
	{
		tmp &= (tmp - 1);
		num++;
	}
	num &= 1;//计算整数中有多少个1,做加法
	return num;
}

/// Walsh函数，求F的walsh系数值，需要输入一个布尔函数F，以及点w
int Walsh(const int F[], const int w)
{
	int sum = 0;
	for (int x = 0; x < (1 << var); x++)
	{
		int num = inner_dot(x, w);
		num ^= F[x];//F[x]+x*w的奇偶性
		sum += num;//1的个数
	}
	return (1 << var) - 2 * sum; //1的个数减去0的个数就是walsh系数值
}

/// 自相关函数
int  Autocorrelation(const int F[], const int a)
{
	int sum = 0;
	for (int x = 0; x < (1 << var); x++)
	{
		if ((F[x ^ a] xor F[x]) == 0) {
			sum++;
		}
		else {
			sum--;
		}
	}
	return sum;
}

/// Δ_f
/// 遍历自相关，绝对值的最大值，越小越好
int Delat_f(const int* F) {
	int D = 0;
	for (int i = 1; i < (1 << var); i++)
	{
		int p = abs(Autocorrelation(F, i));
		if (D < p) {
			D = p;
		}
	}
	return D;
}


/// δ_f
/// 遍历自相关，最大值，越大越好
int delat_f(const int* F) {
	int d = 0;
	for (int i = 1; i < (1 << var); i++)
	{
		int p = Autocorrelation(F, i);
		if (d < p) {
			d = p;
		}
	}
	return d;
}

/// 是否平衡
bool Balanced(const int F[])
{
	return !Walsh(F, 0);
}

/// walsh谱绝对值最大值
int Max_Abs_Walsh(const int F[])
{
	int temp = 0, max_a_w = 0;
	for (int i = 0; i < (1 << var); i++)
	{
		temp = abs(Walsh(F, i));
		if (temp > max_a_w)
		{
			max_a_w = temp;
		}
	}
	return max_a_w;
}

/// 计算布尔函数的非线性度。
int nonlinear(int* F)
{
	int nonlinear = 0;
	nonlinear = (1 << (var - 1)) - Max_Abs_Walsh(F) / 2;
	return nonlinear;
}

/// 是否 bent
bool if_bent(int* f) {
	if (var % 2 != 0) {
		return false;
	}
	else {
		int all_equal = (1 << (var / 2));
		for (int i = 0; i < (1 << var); i++)
		{
			if (abs(Walsh(f, i)) != all_equal)
			{
				return false;
			}
		}
	}
	return true;
}

/// 计算两个布尔函数的汉明距离
int hb(int* bf1, int* bf2)
{
	int hamb = 0;
	for (int i = 0; i < (1 << var); i++)
	{
		if (bf1[i] != bf2[i])
		{
			hamb++;
		}
	}
	return hamb;
}

/// 判断两个布尔函数是不是一样了……
bool ifequal(int* bf1, int* bf2)
{
	for (int i = 0; i < (1 << var); i++)
	{
		if (bf1[i] != bf2[i])
		{
			return false;
		}
	}
	return true;
}

/// 打印相关信息
void print_bf(int* f) {
	int n_0 = 0;
	int n_1 = 0;
	std::cout << "--------------------------\n布尔函数的真值表为：\n";
	for (int i = 0; i < (1 << var); i++)
	{
		if (f[i]) {
			n_1++;
		}
		else {
			n_0++;
		}
		std::cout << f[i];
	}
	std::cout << "\n-----------------------------\n";
	std::cout << "0：" << n_0 << "\n";
	std::cout << "1：" << n_1 << "\n";
	std::cout << "-----------------------------\n";
	std::cout << "非线性度：" << nonlinear(f) << "\n";
	std::cout << "Δ_f：" << Delat_f(f) << "\n";
	std::cout << "最大自相关：" << delat_f(f) << "\n";
	std::cout << "是否bent：" << (if_bent(f) ? "是" : "否") << "\n";
}
